﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Security;

namespace Alex.Library.Log
{
    /// <summary>
    /// 系统日志
    /// </summary>
    public class EventLogger : LoggerBase
    {
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public EventLogger()
        {

        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="eventSource">消息源</param>
        /// <param name="eventId">消息事件的事件ID（0～65535）</param>
        public EventLogger(string eventSource, int eventId)
        {
            this.eventSource = eventSource;
            this.eventId = eventId;
        }

        private string _Host = ".";
        /// <summary>
        /// 获取或设置保存系统日志的机器名，默认为本机
        /// </summary>
        public string Host
        {
            get { return _Host; }
            set { _Host = value; }
        }

        private string _UserName;
        /// <summary>
        /// 获取或设置具有管理员权限账户名称
        /// </summary>
        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value; }
        }

        private string _Domain;
        /// <summary>
        /// 获取或设置Windows域名
        /// </summary>
        public string Domain
        {
            get { return _Domain; }
            set { _Domain = value; }
        }

        private string _Password;
        /// <summary>
        /// 获取或设置管理员登录密码
        /// </summary>
        public string Password
        {
            get { return _Password; }
            set { _Password = value; }
        }

        private string _LogName = "Application";
        /// <summary>
        /// 获取或设置日志名
        /// </summary>
        public string LogName
        {
            get { return _LogName; }
            set { _LogName = value; }
        }

        private int _Category = 0;
        /// <summary>
        /// 获取或设置消息事件类型。
        /// 当前设定：无
        /// </summary>
        public int Category
        {
            get { return _Category; }
            set { _Category = value; }
        }

        private string eventSource = "MyApp";
        /// <summary>
        /// 获取消息事件来源
        /// </summary>
        public string EventSource
        {
            get { return eventSource; }
        }

        private int eventId = -1;
        /// <summary>
        /// 获取消息事件的事件ID（0～65535）
        /// </summary>
        public int EventId
        {
            get { return eventId; }
        }
        
        /// <summary>

        /// 将LogType类型转换成EventLogEntryType类型

        /// </summary>

        /// <param name="type">LogType</param>

        /// <returns>EventLogEntryType</returns>

        /// <exception cref="System.ApplicationException">转换错误时抛出的例外类型</exception>
        private EventLogEntryType GetLogEntryType(LogLevel level)
        {
            switch (level)
            {
                case LogLevel.DEBUG:
                case LogLevel.INFO:
                    return EventLogEntryType.Information;
                case LogLevel.WARN:
                    return EventLogEntryType.Warning;
                case LogLevel.ERROR:
                    return EventLogEntryType.FailureAudit;
                case LogLevel.FATAL:
                    return EventLogEntryType.Error;
                default:
                    return EventLogEntryType.SuccessAudit;
            }
        }

        /// <summary>
        /// 输出到系统日志
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <param name="message">消息内容</param>
        protected override void DoFlush(LogLevel level, string message)
        {
            string msgContent = this.Template.Format(level, message);
            try
            {
                if (!EventLog.SourceExists(eventSource))
                {
                    EventLog.CreateEventSource(eventSource, _LogName);
                }
                EventLog.WriteEntry(eventSource, msgContent, GetLogEntryType(level), eventId, (short)_Category);
            }
            catch (SecurityException)
            {
                //碰到权限不够无法操作系统日志的情况时，模拟本地管理员权限进行操作。
                //提示：当注册表中没有消息事件来源时，会发生该例外                                
                using (ImpersonateAccount sa = new ImpersonateAccount(_UserName, _Domain, _Password))
                {
                    if (!EventLog.SourceExists(eventSource))
                    {
                        EventLog.CreateEventSource(eventSource, _LogName);
                    }
                    EventLog.WriteEntry(eventSource, msgContent, GetLogEntryType(level), eventId, (short)_Category);
                }
            }
        }
    }
}
